<!DOCTYPE html>
<html lang="zh-Hans">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/blog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/blog/css/main.css">


<link rel="stylesheet" href="/blog/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"kriko.gitee.io","root":"/blog/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta property="og:type" content="website">
<meta property="og:title" content="GameDev">
<meta property="og:url" content="https://kriko.gitee.io/blog/index.html">
<meta property="og:site_name" content="GameDev">
<meta property="article:author" content="kriko">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://kriko.gitee.io/blog/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-Hans'
  };
</script>

  <title>GameDev</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/blog/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">GameDev</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/blog/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/blog/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/blog/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/blog/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/blog/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
        <li class="menu-item menu-item-commonweal">

    <a href="/blog/404/" rel="section"><i class="fa fa-heartbeat fa-fw"></i>公益 404</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="https://kriko.gitee.io/blog/2020/11/05/LearnUnityGameFrameWork/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/blog/images/avatar.gif">
      <meta itemprop="name" content="kriko">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="GameDev">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/blog/2020/11/05/LearnUnityGameFrameWork/" class="post-title-link" itemprop="url">LearnUnityGameFrameWork</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2020-11-05 10:10:43 / 修改时间：11:34:13" itemprop="dateCreated datePublished" datetime="2020-11-05T10:10:43+08:00">2020-11-05</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/Unity%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/" itemprop="url" rel="index"><span itemprop="name">Unity学习记录</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="简单介绍"><a href="#简单介绍" class="headerlink" title="简单介绍"></a>简单介绍</h1><p>​    GameFramework 是一个优秀的开源游戏框架，他独特的资源异步加载模式和优秀的代码结构十分值得我去学习。因此本系列文章主要记录了在学习这个框架时，我遇到的一些问题，解决思路以及一些心得体会。通过学习该框架，我希望可以提炼自己的代码整洁性，了解如何独自设计中大型项目的整理逻辑。</p>
<h2 id="一、流程"><a href="#一、流程" class="headerlink" title="一、流程"></a>一、流程</h2><ul>
<li><p>有限状态机</p>
<p>在拿到实例程序<code>StarForce</code>之后，我首先做的事情就是想要找到整个游戏的入口函数。整个GameFramework 设计似乎是打算通过一个有限状态机来管理各个部分的逻辑，游戏每执行到一个状态，首先卸载之前状态，然后执行该状态的初始化函数，再执行每帧更新函数。类似于状态模式的设计，是一个很不错的解耦方式。</p>
<ol>
<li>在GameFramework游戏物体下，存在一个 Procedure，可以通过这个组件来激活可用的流程。每个流程类都继承自 <code>ProcedureBase</code> ,并且可以分别实现<code>OnEnter OnLeave OnUpdate</code> 三个主要的函数，这三个函数都可以获取到<code>procedureOwner</code> 对象。</li>
<li><code>ProcedureComponent</code> 在编写完成流程脚本之后，可以看到该组件上自动将写好的流程显示出来，由于暂时没有去详细研究框架底层代码，我猜测可能是运用了类似反射的机制。不管怎样，通过<code>ProcedureComponent</code> 可以指定需要用到的流程，并将其激活。<code>Entrance Procedure</code> 表示入口流程，需要首先指定一个初试流程。</li>
</ol>
<p>为了测试该模块，我写了一个简单的<code>ProcedureLaunch</code> 类作为整个流程的起始</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">namespace Client &#123;</span><br><span class="line">    public class ProcedureLaunch : ProcedureBase</span><br><span class="line">    &#123;</span><br><span class="line">        protected override void OnInit(IFsm&lt;IProcedureManager&gt; procedureOwner) &#123;</span><br><span class="line">            base.OnInit(procedureOwner);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        protected override void OnEnter(IFsm&lt;IProcedureManager&gt; procedureOwner) &#123;</span><br><span class="line">            base.OnEnter(procedureOwner);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        protected override void OnUpdate(IFsm&lt;IProcedureManager&gt; procedureOwner, float elapseSeconds, float realElapseSeconds) &#123;</span><br><span class="line">            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);</span><br><span class="line">            ChangeState&lt;ProcedurePreload&gt;(procedureOwner);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        protected override void OnLeave(IFsm&lt;IProcedureManager&gt; procedureOwner, bool isShutdown) &#123;</span><br><span class="line">            base.OnLeave(procedureOwner, isShutdown);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该类很简单，就是在执行一帧之后进入到下一个流程，预加载流程。在<code>ProcedureComponent</code> 激活该流程，同时在<code>Entrance Procedure</code> 指定该流程为入口。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">namespace Client &#123;</span><br><span class="line">    public class ProcedurePreload : ProcedureBase</span><br><span class="line">    &#123;</span><br><span class="line">        protected override void OnInit(IFsm&lt;IProcedureManager&gt; procedureOwner) &#123;</span><br><span class="line">            base.OnInit(procedureOwner);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        protected override void OnEnter(IFsm&lt;IProcedureManager&gt; procedureOwner) &#123;</span><br><span class="line">            base.OnEnter(procedureOwner);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        protected override void OnUpdate(IFsm&lt;IProcedureManager&gt; procedureOwner, float elapseSeconds, float realElapseSeconds) &#123;</span><br><span class="line">            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);</span><br><span class="line">            Log.Info(&quot;Ok!We are in preload procedure!&quot;);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        protected override void OnLeave(IFsm&lt;IProcedureManager&gt; procedureOwner, bool isShutdown) &#123;</span><br><span class="line">            base.OnLeave(procedureOwner, isShutdown);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<img src="../images/procedure_01.png"  />

<ul>
<li>图1.1 <code>ProcedurePreload</code> 打印结果</li>
</ul>
<p>图1.1 展示了上述流程打印的结果，从Info来看，正确的执行了代码逻辑，同时我们也可以去观察一下之前提到的<code>ProcedureComponent</code> 组件。</p>
<p><img src="../images/procedure_02.png" alt=""></p>
<ul>
<li>图1.2 <code>ProcedureComponent</code> 组件显示</li>
</ul>
<p>注意到红色箭头指向，表示目前已经运行到了<code>ProcedurPreload</code>  至此一个简单的流程已经完成。</p>
<p>使用流程，可以很自然的形成一种对游戏逻辑分块的思想，比如分离登录状态，资源加载状态，游戏开始状态，主游戏状态，游戏结束状态等等。</p>
</li>
</ul>
<h2 id="DataTable"><a href="#DataTable" class="headerlink" title="DataTable"></a>DataTable</h2><ul>
<li><p>简介</p>
<p>简单的研究完流程之后，就可以更进一步学习这个框架了，毕竟是找到了源头。由于<code>StarForce</code>封装的过于复杂，我们可以先选择一个感兴趣的方向研究，这里我选择了和数据有关的DataTable。</p>
</li>
<li><p>理解</p>
</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="https://kriko.gitee.io/blog/2020/07/14/C-Multithreading/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/blog/images/avatar.gif">
      <meta itemprop="name" content="kriko">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="GameDev">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/blog/2020/07/14/C-Multithreading/" class="post-title-link" itemprop="url">C++多线程编程（基于WindowsAPI）</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-07-14 09:12:18" itemprop="dateCreated datePublished" datetime="2020-07-14T09:12:18+08:00">2020-07-14</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-07-16 09:28:55" itemprop="dateModified" datetime="2020-07-16T09:28:55+08:00">2020-07-16</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/C-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B/" itemprop="url" rel="index"><span itemprop="name">C++多线程编程</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p><strong>第一章 解释线程模型</strong></p>
<hr>
<p><strong>1.1 解释线程模型</strong></p>
<p>引发线程创建的主要事件：</p>
<ol>
<li>系统初始化</li>
<li>正在运行的线程创建线程的系统调用</li>
<li>用户创建新进程</li>
<li>启动批处理作业</li>
</ol>
<p>在windows中我们可以通过<code>CreateProcess</code>函数来在程序中创建一个进程，<code>CreateProcess</code>函数原型定义如下：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">BOOL CreateProcess </span><br><span class="line">( </span><br><span class="line">LPCTSTR lpApplicationName, </span><br><span class="line">LPTSTR lpCommandLine, </span><br><span class="line">LPSECURITY_ATTRIBUTES lpProcessAttributes，</span><br><span class="line">LPSECURITY_ATTRIBUTES lpThreadAttributes, </span><br><span class="line">BOOL bInheritHandles, </span><br><span class="line">DWORD dwCreationFlags, </span><br><span class="line">LPVOID lpEnvironment, </span><br><span class="line">LPCTSTR lpCurrentDirectory, </span><br><span class="line">LPSTARTUPINFO lpStartupInfo, </span><br><span class="line">LPPROCESS_INFORMATION lpProcessInformation </span><br><span class="line">);</span><br></pre></td></tr></table></figure>

<blockquote>
<p>参数说明</p>
</blockquote>
<p><code>lpApplicationName</code> 表示 可执行程序的名称或者路径。该参数必须是一个<code>const char*</code>类型数据</p>
<p><code>lpCommandLine</code> 表示 命令行参数，该参数传递的是一个字符串变量而不是常量。一般可以使用</p>
<blockquote>
<p><code>TCHAR cmdLine[] = TEXT(&quot;XXX.exe X Y&quot;)</code> 形式的写法，将<code>cmdLine</code>指针作为参数传入，此时就不需要在 <code>lpApplicationName</code> 参数中指定程序名，赋值为<code>NULL</code> 就可以。</p>
<p>如果依旧在<code>lpApplicationName</code> 中传入程序名称，注意cmdLine的写法应该是<code>TEXT(&quot; X&quot;)</code>，需要有一个空格。</p>
</blockquote>
<p><code>lpProcessAttributes</code> 表示 为进程使用的系统安全性指针，一般为NULL</p>
<p><code>lpThreadAttributes</code> 表示 为线程使用的系统安全性指针，一般为NULL</p>
<p><code>bInheritHandles</code> 表示新进程句柄是否可以继承现有进程所有可继承的句柄，新进程拥有继承句柄的完全相同的值和访问权限。</p>
<p><code>dwCreationFlags</code> 用于设置新进程创建的方式</p>
<p><code>lpEnvironment</code> 新进程的环境，传入NULL表示继承原进程的环境</p>
<p><code>lpCurrentDirectory</code> 该参数用于设置新进程的当前驱动器和目录</p>
<p><code>lpStartupInfo</code> 这个参数指向一个STARTUPINFO或STARTUPINFOEX的结构,一般应用程序会期待仅使用默认值</p>
<p><code>lpProcessInformation</code> 指向LPPROCESS_INFOMATION结构的指针，这个结构由调用CreateProcess的进程创建，由CreateProcess更改，用于返回新建进程的信息</p>
<blockquote>
<p>例程</p>
</blockquote>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;Windows.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;tchar.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> _tmain(<span class="keyword">int</span> argc,TCHAR* argv[])</span><br><span class="line">&#123;</span><br><span class="line">	STARTUPINFO startupInfo = &#123; <span class="keyword">sizeof</span>(startupInfo) &#125;;	</span><br><span class="line">	PROCESS_INFORMATION processinfomation = &#123; <span class="number">0</span> &#125;;	</span><br><span class="line"></span><br><span class="line">	BOOL bSuccess = CreateProcess(</span><br><span class="line">		TEXT(<span class="string">"C:\\Windows\\notepad.exe"</span>),<span class="literal">NULL</span>,<span class="literal">NULL</span>,</span><br><span class="line">		<span class="literal">NULL</span>,FALSE,<span class="literal">NULL</span>,<span class="literal">NULL</span>,<span class="literal">NULL</span>,</span><br><span class="line">		&amp;startupInfo,&amp;processinfomation</span><br><span class="line">	);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (bSuccess)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Process Create Success \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Process ID \t"</span></span><br><span class="line">			&lt;&lt; processinfomation.dwProcessId &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">else</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Create Process \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError() &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> _tsystem(_T(<span class="string">"PAUSE"</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>分析</p>
</blockquote>
<ol>
<li>操作系统将会为进程提供进程标识符，该标识符可以在某些系统API(如<code>OpenProcess</code>函数)中转换为进程句柄。</li>
<li>主线程可以使用 <code>WaitForInputHandle</code>函数来等待用户完成输入。<code>CreateProcess</code>不会在进程完成初始化操作之后返回。</li>
<li>使用<code>ExitProcess</code>函数可以终止进程，并且给所有的DLL都发送一条终止通知。</li>
</ol>
<blockquote>
<p>更多讨论</p>
</blockquote>
<p>进程可能处于的三种状态</p>
<ol>
<li>运行</li>
<li>就绪 该进程可以运行但在等待它的时间片来临</li>
<li>阻塞 在某些事件发生前，该进程无法运行</li>
</ol>
<p><strong>1.2 进程的实现</strong></p>
<p>进程控制模块（PCB）是操作系统为了管理进程，在内核中设置的一种数据结构，常见的部分可以分为3大类：</p>
<ol>
<li>进程标识数据</li>
<li>进程状态数据</li>
<li>进程控制数据</li>
</ol>
<blockquote>
<p>例程</p>
</blockquote>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;Windows.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;tchar.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;winternl.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">typedef</span> <span class="title">NTSTATUS</span><span class="params">(NTAPI* QEURYINFORMATIONPROCESS)</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">	IN HANDLE ProcessHandle,</span></span></span><br><span class="line"><span class="function"><span class="params">	IN PROCESSINFOCLASS processinfoClass,</span></span></span><br><span class="line"><span class="function"><span class="params">	OUT PVOID ProcessInfomation,</span></span></span><br><span class="line"><span class="function"><span class="params">	IN ULONG ProcessInfomationLength,</span></span></span><br><span class="line"><span class="function"><span class="params">	OUT PULONG ReturnLength OPTIONAL</span></span></span><br><span class="line"><span class="function"><span class="params">	)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> _tmain(<span class="keyword">int</span> argc,TCHAR* argv[])</span><br><span class="line">&#123;</span><br><span class="line">	STARTUPINFO startupInfo = &#123; <span class="keyword">sizeof</span>(startupInfo) &#125;;	</span><br><span class="line">	PROCESS_INFORMATION processinfomation = &#123; <span class="number">0</span> &#125;;	</span><br><span class="line"></span><br><span class="line">	BOOL bSuccess = CreateProcess(</span><br><span class="line">		TEXT(<span class="string">"C:\\Windows\\notepad.exe"</span>),<span class="literal">NULL</span>,<span class="literal">NULL</span>,</span><br><span class="line">		<span class="literal">NULL</span>,FALSE,<span class="literal">NULL</span>,<span class="literal">NULL</span>,<span class="literal">NULL</span>,</span><br><span class="line">		&amp;startupInfo,&amp;processinfomation</span><br><span class="line">	);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (bSuccess)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Process Create Success \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Process ID \t"</span></span><br><span class="line">			&lt;&lt; processinfomation.dwProcessId &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"></span><br><span class="line">		PROCESS_BASIC_INFORMATION pbi;</span><br><span class="line">		ULONG uLength = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">		HMODULE hDll = LoadLibrary(TEXT(<span class="string">"C:\\Windows\\System32\\ntdll.dll"</span>));</span><br><span class="line">		<span class="keyword">if</span> (hDll)</span><br><span class="line">		&#123;</span><br><span class="line">			QEURYINFORMATIONPROCESS QueryInformationProcess = (QEURYINFORMATIONPROCESS)GetProcAddress(hDll,<span class="string">"NtQueryInformationProcess"</span>);</span><br><span class="line">			<span class="keyword">if</span> (QueryInformationProcess)</span><br><span class="line">			&#123;</span><br><span class="line">				NTSTATUS ntStatus = QueryInformationProcess(</span><br><span class="line">					processinfomation.hProcess,</span><br><span class="line">					PROCESSINFOCLASS::ProcessBasicInformation,</span><br><span class="line">					&amp;pbi,<span class="keyword">sizeof</span>(pbi),&amp;uLength);</span><br><span class="line"></span><br><span class="line">				<span class="keyword">if</span> (NT_SUCCESS(ntStatus))</span><br><span class="line">				&#123;</span><br><span class="line">					<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Process ID (From PCB) \t"</span></span><br><span class="line">						&lt;&lt; pbi.UniqueProcessId &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">				&#125;</span><br><span class="line">				<span class="keyword">else</span></span><br><span class="line">				&#123;</span><br><span class="line">					<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Open PCB!\n"</span></span><br><span class="line">						&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError()</span><br><span class="line">						&lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">				&#125;</span><br><span class="line">			&#125;</span><br><span class="line">			<span class="keyword">else</span></span><br><span class="line">			&#123;</span><br><span class="line">				<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Get NtQueryInformationProcess function \n"</span></span><br><span class="line">					&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError()</span><br><span class="line">					&lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">else</span></span><br><span class="line">		&#123;</span><br><span class="line">			<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not load ntdll.dll!\n"</span></span><br><span class="line">				&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError()</span><br><span class="line">				&lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">else</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Create Process \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError() &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> _tsystem(_T(<span class="string">"PAUSE"</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>1.3 进程间通信（IPC）</strong></p>
<p>竞态条件： 当多个进程共享同一个数据，并且需要对这个数据进行读写操作，并且该操作对执行顺序敏感此时就容易发生竞态条件。</p>
<p>我们可以通过互斥或者提供独占访问共享对象的方法来避免竞态条件的产生。</p>
<p>使用临界区可以避免竞态条件出现，但是要注意以下几点：</p>
<ol>
<li>不允许同时有两个进程都在临界区中</li>
<li>不应该对CPU速度以及数量做任何假设</li>
<li>在临界区外部的进程不得阻塞其他进程</li>
<li>进程不应该永远在等待进入临界区</li>
</ol>
<blockquote>
<p>例程</p>
</blockquote>
<p><u>工作进程</u></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;Windows.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;tchar.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> COMMUNICATION_OBJECT_NAME TEXT(<span class="meta-string">"__FILE_MAPPING__"</span>)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SYNCHORNIZING_MUTEX_NAME TEXT(<span class="meta-string">"__TEST_MUTEX__"</span>)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> _<span class="title">tagCOMMUNICATIONOBJECT</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">	HWND hWndCLient;</span><br><span class="line">	BOOL bExitLoop;</span><br><span class="line">	LONG lSleepTimeout;</span><br><span class="line">&#125; COMMUNICATIONOBJECT,*PCOMMUNICATIONOBJECT;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> _tmain(<span class="keyword">int</span> argc,TCHAR* argv[])</span><br><span class="line">&#123;</span><br><span class="line">	HBRUSH hBrush = <span class="literal">NULL</span>;</span><br><span class="line">	<span class="keyword">if</span> (_tcscmp(TEXT(<span class="string">"blue"</span>),argv[<span class="number">1</span>]) == <span class="number">0</span>)	<span class="comment">//比较cmdLine参数</span></span><br><span class="line">	&#123;</span><br><span class="line">		hBrush = CreateSolidBrush(RGB(<span class="number">0</span>,<span class="number">0</span>,<span class="number">255</span>));	<span class="comment">//创建画刷</span></span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">else</span></span><br><span class="line">	&#123;</span><br><span class="line">		hBrush = CreateSolidBrush(RGB(<span class="number">255</span>,<span class="number">0</span>,<span class="number">0</span>));</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	HWND hWnd = <span class="literal">NULL</span>;</span><br><span class="line">	HDC hDC = <span class="literal">NULL</span>;</span><br><span class="line">	RECT rectClient = &#123; <span class="number">0</span> &#125;;</span><br><span class="line">	LONG lWaitTimeout = <span class="number">0</span>;</span><br><span class="line">	HANDLE hFileMapping = <span class="literal">NULL</span>;</span><br><span class="line">	PCOMMUNICATIONOBJECT pCommObject = <span class="literal">NULL</span>;	<span class="comment">//Map出的内存指针</span></span><br><span class="line">	BOOL bContinueLoop = TRUE;</span><br><span class="line"></span><br><span class="line">	HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, SYNCHORNIZING_MUTEX_NAME);	<span class="comment">//打开一个已命名的互斥锁</span></span><br><span class="line">	hFileMapping = OpenFileMapping(FILE_MAP_READ, FALSE, COMMUNICATION_OBJECT_NAME);	<span class="comment">//打开一个文件映射</span></span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (hFileMapping)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">while</span> (bContinueLoop)</span><br><span class="line">		&#123;</span><br><span class="line">			WaitForSingleObject(hMutex, INFINITE);	<span class="comment">//等待直到可以进入临界区</span></span><br><span class="line">			pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(</span><br><span class="line">				hFileMapping,</span><br><span class="line">				FILE_MAP_READ,</span><br><span class="line">				<span class="number">0</span>, <span class="number">0</span>,</span><br><span class="line">				<span class="keyword">sizeof</span>(COMMUNICATIONOBJECT)</span><br><span class="line">			);	<span class="comment">//将映射文件和指针绑定</span></span><br><span class="line"></span><br><span class="line">			<span class="keyword">if</span> (pCommObject)</span><br><span class="line">			&#123;</span><br><span class="line">				bContinueLoop = !pCommObject-&gt;bExitLoop;</span><br><span class="line">				hWnd = pCommObject-&gt;hWndCLient;</span><br><span class="line">				lWaitTimeout = pCommObject-&gt;lSleepTimeout;</span><br><span class="line">				UnmapViewOfFile(pCommObject);</span><br><span class="line">				hDC = GetDC(hWnd);</span><br><span class="line">				<span class="keyword">if</span> (GetClientRect(hWnd, &amp;rectClient))</span><br><span class="line">				&#123;</span><br><span class="line">					FillRect(hDC, &amp;rectClient, hBrush);</span><br><span class="line">				&#125;</span><br><span class="line">				ReleaseDC(hWnd, hDC);</span><br><span class="line">				Sleep(lWaitTimeout);	<span class="comment">//等待，此时这个进程一直处于临界区，所以其他进程就一直等待该进程完成Sleep</span></span><br><span class="line">			&#125;</span><br><span class="line">			ReleaseMutex(hMutex);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	CloseHandle(hFileMapping);</span><br><span class="line">	CloseHandle(hMutex);</span><br><span class="line">	DeleteObject(hBrush);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><u>客户端进程</u></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;Windows.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;tchar.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> COMMUNICATION_OBJECT_NAME TEXT(<span class="meta-string">"__FILE_MAPPING__"</span>)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SYNCHORNIZING_MUTEX_NAME TEXT(<span class="meta-string">"__TEST_MUTEX__"</span>)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> WINDOW_CLASS_NAME TEXT(<span class="meta-string">"__TEMPWNDCLASS__"</span>)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> BUTTON_CLOSE 100</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> _<span class="title">tagCOMMUNICATIONOBJECT</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">	HWND hWndCLient;</span><br><span class="line">	BOOL bExitLoop;</span><br><span class="line">	LONG lSleepTimeout;</span><br><span class="line">&#125; COMMUNICATIONOBJECT, * PCOMMUNICATIONOBJECT;</span><br><span class="line"></span><br><span class="line"><span class="function">LRESULT CALLBACK <span class="title">WndProc</span><span class="params">(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)</span></span>;</span><br><span class="line"><span class="function">HWND <span class="title">InitializeWnd</span><span class="params">()</span></span>;</span><br><span class="line">PCOMMUNICATIONOBJECT pCommObject = <span class="literal">NULL</span>;</span><br><span class="line">HANDLE hFileMapping = <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> _tmain(<span class="keyword">int</span> argc,TCHAR* argv[])</span><br><span class="line">&#123;</span><br><span class="line">	<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Create IPC Demo"</span> &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">	HWND hWnd = InitializeWnd();</span><br><span class="line">	<span class="keyword">if</span> (!hWnd)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Create Window \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError()</span><br><span class="line">			&lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">		<span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	HANDLE hMutex = CreateMutex(<span class="literal">NULL</span>, FALSE, SYNCHORNIZING_MUTEX_NAME);	<span class="comment">//创建互斥锁</span></span><br><span class="line">	<span class="keyword">if</span> (!hMutex)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Create Mutex \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError()</span><br><span class="line">			&lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">		<span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	hFileMapping = CreateFileMapping((HANDLE)<span class="number">-1</span>, <span class="literal">NULL</span>, PAGE_READWRITE, <span class="number">0</span>, <span class="keyword">sizeof</span>(COMMUNICATIONOBJECT), COMMUNICATION_OBJECT_NAME);</span><br><span class="line">	<span class="keyword">if</span> (!hFileMapping)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Create FileMapping \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError()</span><br><span class="line">			&lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">		<span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">	<span class="keyword">if</span> (pCommObject)</span><br><span class="line">	&#123;</span><br><span class="line">		pCommObject-&gt;bExitLoop = FALSE;</span><br><span class="line">		pCommObject-&gt;hWndCLient = hWnd;</span><br><span class="line">		pCommObject-&gt;lSleepTimeout = <span class="number">250</span>;</span><br><span class="line">		UnmapViewOfFile(pCommObject);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	STARTUPINFO startupInfoRed = &#123; <span class="number">0</span> &#125;;</span><br><span class="line">	PROCESS_INFORMATION processinformationRed = &#123; <span class="number">0</span> &#125;;</span><br><span class="line">	STARTUPINFO startupInfoBlue = &#123; <span class="number">0</span> &#125;;</span><br><span class="line">	PROCESS_INFORMATION processinformationBlue = &#123; <span class="number">0</span> &#125;;</span><br><span class="line"></span><br><span class="line">	TCHAR red[] = TEXT(<span class="string">"..\\Debug\\002IPCWorker.exe red"</span>);</span><br><span class="line">	BOOL bSuccess = CreateProcess(<span class="literal">NULL</span>,</span><br><span class="line">		red, <span class="literal">NULL</span>, <span class="literal">NULL</span>, FALSE,</span><br><span class="line">		<span class="number">0</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>, &amp;startupInfoRed, &amp;processinformationRed);</span><br><span class="line">	<span class="keyword">if</span> (!bSuccess)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Create Process \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError()</span><br><span class="line">			&lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">		<span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	TCHAR blue[] = TEXT(<span class="string">"..\\Debug\\002IPCWorker.exe blue"</span>);</span><br><span class="line">	bSuccess = CreateProcess(<span class="literal">NULL</span>,</span><br><span class="line">		blue, <span class="literal">NULL</span>, <span class="literal">NULL</span>, FALSE,</span><br><span class="line">		<span class="number">0</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>, &amp;startupInfoBlue, &amp;processinformationBlue);</span><br><span class="line">	<span class="keyword">if</span> (!bSuccess)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"Can not Create Process \n"</span></span><br><span class="line">			&lt;&lt; <span class="string">"Error Code \t"</span> &lt;&lt; GetLastError()</span><br><span class="line">			&lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">		<span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	MSG msg = &#123; <span class="number">0</span> &#125;;</span><br><span class="line">	<span class="keyword">while</span> (GetMessage(&amp;msg,<span class="literal">NULL</span>,<span class="number">0</span>,<span class="number">0</span>))</span><br><span class="line">	&#123;</span><br><span class="line">		TranslateMessage(&amp;msg);</span><br><span class="line">		DispatchMessage(&amp;msg);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	UnregisterClass(WINDOW_CLASS_NAME, GetModuleHandle(<span class="literal">NULL</span>));</span><br><span class="line">	CloseHandle(hFileMapping);</span><br><span class="line">	CloseHandle(hMutex);</span><br><span class="line"></span><br><span class="line">	<span class="built_in">std</span>::<span class="built_in">cout</span> &lt;&lt; <span class="string">"End Process"</span> &lt;&lt; <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">LRESULT CALLBACK <span class="title">WndProc</span><span class="params">(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">switch</span> (uMsg)</span><br><span class="line">	&#123;</span><br><span class="line">	<span class="keyword">case</span> WM_COMMAND:</span><br><span class="line">		<span class="keyword">switch</span> (LOWORD(wParam))</span><br><span class="line">		&#123;</span><br><span class="line">		<span class="keyword">case</span> BUTTON_CLOSE:</span><br><span class="line">			PostMessage(hWnd,WM_CLOSE,<span class="number">0</span>,<span class="number">0</span>);</span><br><span class="line">			<span class="keyword">break</span>;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">break</span>;</span><br><span class="line">	<span class="keyword">case</span> WM_DESTROY:</span><br><span class="line">		pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">		<span class="keyword">if</span> (pCommObject)</span><br><span class="line">		&#123;</span><br><span class="line">			pCommObject-&gt;bExitLoop = TRUE;</span><br><span class="line">			UnmapViewOfFile(pCommObject);</span><br><span class="line">		&#125;</span><br><span class="line">		PostQuitMessage(<span class="number">0</span>);</span><br><span class="line">		<span class="keyword">break</span>;</span><br><span class="line">	<span class="keyword">default</span>:</span><br><span class="line">		<span class="keyword">return</span> DefWindowProc(hWnd, uMsg, wParam, lParam);</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">HWND <span class="title">InitializeWnd</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	WNDCLASSEX wndEX = &#123; <span class="number">0</span> &#125;;</span><br><span class="line">	wndEX.cbSize = <span class="keyword">sizeof</span>(wndEX);</span><br><span class="line">	wndEX.style = CS_HREDRAW | CS_VREDRAW;</span><br><span class="line">	wndEX.lpfnWndProc = WndProc;</span><br><span class="line">	wndEX.cbClsExtra = <span class="number">0</span>;</span><br><span class="line">	wndEX.cbWndExtra = <span class="number">0</span>;</span><br><span class="line">	wndEX.hInstance = GetModuleHandle(<span class="literal">NULL</span>);</span><br><span class="line">	wndEX.hbrBackground = (HBRUSH)(COLOR_WINDOW + <span class="number">1</span>);</span><br><span class="line">	wndEX.lpszMenuName = <span class="literal">NULL</span>;</span><br><span class="line">	wndEX.lpszClassName = WINDOW_CLASS_NAME;</span><br><span class="line">	wndEX.hCursor = LoadCursor(<span class="literal">NULL</span>, IDC_ARROW);</span><br><span class="line">	wndEX.hIcon = LoadIcon(wndEX.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));</span><br><span class="line">	wndEX.hIconSm = LoadIcon(wndEX.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));</span><br><span class="line">	<span class="keyword">if</span> (!RegisterClassEx(&amp;wndEX))</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	HWND hWnd = CreateWindow(wndEX.lpszClassName, TEXT(<span class="string">"IPC Process Demo"</span>),</span><br><span class="line">		WS_OVERLAPPEDWINDOW, <span class="number">200</span>, <span class="number">200</span>, <span class="number">400</span>, <span class="number">300</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>,</span><br><span class="line">		wndEX.hInstance,<span class="literal">NULL</span>);</span><br><span class="line">	<span class="keyword">if</span> (!hWnd)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">	&#125;</span><br><span class="line">	HWND hButton = CreateWindow(TEXT(<span class="string">"BUTTON"</span>), TEXT(<span class="string">"Close"</span>),</span><br><span class="line">		WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,</span><br><span class="line">		<span class="number">275</span>, <span class="number">225</span>, <span class="number">100</span>, <span class="number">25</span>, hWnd, (HMENU)BUTTON_CLOSE, wndEX.hInstance, <span class="literal">NULL</span>);</span><br><span class="line">	HWND hStatic = CreateWindow(TEXT(<span class="string">"STATIC"</span>), TEXT(<span class="string">""</span>),</span><br><span class="line">		WS_CHILD | WS_VISIBLE,</span><br><span class="line">		<span class="number">10</span>, <span class="number">10</span>, <span class="number">365</span>, <span class="number">205</span>, hWnd, <span class="literal">NULL</span>, wndEX.hInstance, <span class="literal">NULL</span>);</span><br><span class="line">	ShowWindow(hWnd, SW_SHOW);</span><br><span class="line">	UpdateWindow(hWnd);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> hStatic;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>分析</p>
</blockquote>
<p>进程间共享数据可以通过<code>CreateFileMapping</code> 等一系列系统函数完成操作，具体步骤如下所示：</p>
<ol>
<li><p>创建内存映射文件 <code>CreateFileMapping</code></p>
<p>可以将磁盘上真正存在的物理文件映射为一个虚拟文件</p>
<p><code>HANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,size，name)</code></p>
<blockquote>
<p>说明</p>
<p>​    hFile: 对应的文件句柄，如果传递<code>(HANDLE)-1</code>那么认为磁盘上不会产生任何文件，当想要共享内存中的数据而不是磁盘数据的时候很有用。</p>
<p>​    NULL: 安全属性，一般可以设为NULL</p>
<p>​    RAGE_READWRITE: 标记该内存区域可读可写</p>
<p>​    0：文件开始偏移</p>
<p>​    size: 文件结束偏移</p>
<p>​    name: 标识虚拟文件名字，当使用<code>OpenFileMapping</code> 函数时，需要传递该参数来获取虚拟文件映射句柄</p>
</blockquote>
</li>
<li><p>加载内存映射 <code>MapViewOfFile</code></p>
<p>可以认为将内存和虚拟文件进行绑定，以后对该内存指针的操作就是对该物理文件内容的操作。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">TCHAR* pcText = <span class="literal">NULL</span>;</span><br><span class="line">pcText = (TCHAR)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,<span class="number">0</span>,<span class="number">0</span>,<span class="built_in">size</span>);</span><br></pre></td></tr></table></figure>

<blockquote>
<p>说明</p>
<p>​    hFileMapping : 之前通过<code>CreateFileMapping</code> 函数创建的虚拟文件句柄</p>
<p>​    FILE_MAP_ALL_ACCESS : 访问模式，可以等价视为<code>FILE_MAP_WRITE</code></p>
<p>​    0,0 : 虚拟文件开始的位置</p>
<p>​    size ：映射文件的大小</p>
</blockquote>
</li>
<li><p>卸载内存映射 <code>UnmapViewOfFile</code></p>
<p><code>UnmapViewOfFile((PVOID)pcText)</code></p>
</li>
<li><p>关闭句柄</p>
<p><code>CloseHandle(hFileMapping)</code></p>
</li>
<li><p>打开虚拟文件映射 <code>OpenFileMapping</code></p>
<p>根据指定的虚拟文件名，获取虚拟文件句柄，之后可以通过<code>MapViewOfFile</code>函数直接操作内存映射指针</p>
<p><code>HANDLE hFileMapping = OpenFileMapping(FILE_MAP_READ,FALSE,name)</code></p>
<blockquote>
<p>说明</p>
<p>​    FILE_MAP_READ : 标志访问模式，也可以传递<code>FILE_MAP_ALL_ACCESS</code></p>
<p>​    FALSE : 是否继承</p>
<p>​    name ：指定虚拟文件名称，需要与<code>CreateFileMapping</code>中虚拟文件名一致</p>
</blockquote>
</li>
</ol>
<p>为了保证多个进程之间能够共享某一块数据，并且不会出现竞态问题，需要操作系统引入互斥量的概念。在windows系统中，可以通过<strong>Mutex</strong>句柄来完成该操作，详细步骤如下：</p>
<ol>
<li><p>创建互斥量 <code>CreateMutex</code></p>
<p><code>HANDLE hMutex = CreateMutex(NULL,FALSE,NAME)</code></p>
<blockquote>
<p>说明</p>
<p>​    该函数返回一个互斥量句柄</p>
<p>​    NULL : 安全属性</p>
<p>​    FALSE : 如果置为TRUE 那么该线程就拥有最初互斥量的所有权</p>
<p>​    NAME : 标志该互斥量的名称</p>
</blockquote>
</li>
<li><p>根据互斥量名称获取互斥量句柄 <code>OpenMutex</code></p>
<p><code>HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,MAME)</code></p>
<blockquote>
<p>说明</p>
<p>​    MUTEX_ALL_ACCESS : 获取所有可能获取的权限</p>
<p>​    FALSE : 继承性</p>
<p>​    NAME : 在<code>CreateMutex</code>中指定的NAME</p>
</blockquote>
</li>
<li><p>等待临界区的到来 <code>WaitForSingleObject</code></p>
<p>进程会阻塞在这里，直达可以获取该互斥量</p>
<p><code>WaitForSingleObject(hMutex,INFINITE)</code></p>
<blockquote>
<p>说明</p>
<p>​    hMutex : 互斥量句柄</p>
<p>​    INFINITE : 阻塞时间，INFINITE表示等待无限长时间</p>
</blockquote>
</li>
<li><p>解除互斥量 <code>ReleaseMutex(hMutex)</code></p>
<p>解除互斥量，其他进程将有可能获取该互斥量</p>
</li>
</ol>
<p><strong>1.4 典型IPC问题</strong></p>
<p>在进行多进程程序设计的时候，经常会因为对同一变量在多道进程中进行操作而产生同步问题。下面就介绍一个非常经典的哲学家就餐问题，并就这一问题提出解决多进程同步问题的解决方案。</p>
<p>餐桌上有5名哲学家围成一圈，每个人身边都有一副餐叉，必须使用两副餐叉才能叉起意大利面。每名哲学家在进食完成之后都会思考一段时间（Sleep/DoSomeThing），然后再次进行进餐操作。设计一道多进程程序模拟以上过程。</p>
<p>可能的问题是，如果每个进程都进行同一个操作，例如拿起左手边的餐叉，那么由于没有一位哲学家能够拿起右手边的餐叉，那么程序也就会因此死锁。</p>
<p>这里提出的方案是，使用<strong>windows</strong>操作系统内核对象<code>Semaphore</code>信号量，每次只允许固定数量的进程运行（即锁住固定数量的进程），其他进程会等待信号量解锁，这样就不会出现所有的餐叉都被拿起的情况，并且程序保证了一定的多进程效率。</p>
<blockquote>
<p>例程</p>
</blockquote>
<p><u>服务器进程</u></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;Windows.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;tchar.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> EATING_TIME 1000</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> PHILOSOPHER_COUNT 5</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> WM_INVALIDATE WM_USER+1</span></span><br><span class="line"></span><br><span class="line">TCHAR szSemaphoreName[] = TEXT(<span class="string">"__PD_SEMAPHORE__"</span>);	<span class="comment">//信号量名称</span></span><br><span class="line">TCHAR szFileMappingName[] = TEXT(<span class="string">"__SHARED_FILE_MAPPING__"</span>);	<span class="comment">//进程共享虚拟映射文件名称</span></span><br><span class="line">BOOL bExitApplication = FALSE;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> _<span class="title">tagCOMMUNICATIONOBJECT</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">	HWND hWnd;</span><br><span class="line">	BOOL bExitApplication;</span><br><span class="line">	<span class="keyword">int</span> iPhilosopherArray[PHILOSOPHER_COUNT];</span><br><span class="line">	<span class="keyword">int</span> iPhilosopherCounter;</span><br><span class="line">&#125;COMMUNICATIONOBJECT,*PCOMMUNICATIONOBJECT;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">Eating</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> _tmain(<span class="keyword">int</span> argc,TCHAR* argv[])</span><br><span class="line">&#123;</span><br><span class="line">	HWND hConsole = GetConsoleWindow();</span><br><span class="line">	ShowWindow(hConsole, SW_HIDE);</span><br><span class="line">	<span class="keyword">int</span> index = (<span class="keyword">int</span>)_tcstol(argv[<span class="number">0</span>], <span class="literal">NULL</span>, <span class="number">10</span>);	<span class="comment">//将所有可以转换的数字进行转换</span></span><br><span class="line">	HANDLE hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szFileMappingName);	<span class="comment">//获取虚拟文件句柄</span></span><br><span class="line">	<span class="keyword">while</span> (!bExitApplication)</span><br><span class="line">	&#123;</span><br><span class="line">		HANDLE hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, szSemaphoreName);</span><br><span class="line">		WaitForSingleObject(hSemaphore, INFINITE);	<span class="comment">//等待信号量</span></span><br><span class="line">		PCOMMUNICATIONOBJECT pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(</span><br><span class="line">			hFileMapping, FILE_MAP_ALL_ACCESS,</span><br><span class="line">			<span class="number">0</span>, <span class="number">0</span>, <span class="keyword">sizeof</span>(COMMUNICATIONOBJECT));	<span class="comment">//根据虚拟文件名获取内存指针</span></span><br><span class="line">		bExitApplication = pCommObject-&gt;bExitApplication;</span><br><span class="line">		<span class="keyword">if</span> (!pCommObject-&gt;iPhilosopherArray[</span><br><span class="line">			(index + pCommObject-&gt;iPhilosopherCounter - <span class="number">1</span>) % pCommObject-&gt;iPhilosopherCounter]	<span class="comment">//上一个是否通过</span></span><br><span class="line">			&amp;&amp; !pCommObject-&gt;iPhilosopherArray[</span><br><span class="line">				(index + <span class="number">1</span>) % pCommObject-&gt;iPhilosopherCounter])									<span class="comment">//下一个是否通过</span></span><br><span class="line">		&#123;</span><br><span class="line">			pCommObject-&gt;iPhilosopherArray[index] = <span class="number">1</span>;											<span class="comment">//标记该哲学家已经通过</span></span><br><span class="line">			Eating();																			<span class="comment">//阻塞进程</span></span><br><span class="line">		&#125;</span><br><span class="line">			SendMessage(pCommObject-&gt;hWnd, WM_INVALIDATE, <span class="number">0</span>, <span class="number">0</span>);								<span class="comment">//通过虚拟文件，向客户端进程发送消息</span></span><br><span class="line">			pCommObject-&gt;iPhilosopherArray[index] = <span class="number">0</span>;											<span class="comment">//标志该哲学家已经完成动作</span></span><br><span class="line">			ReleaseSemaphore(hSemaphore, <span class="number">1</span>, <span class="literal">NULL</span>);</span><br><span class="line">			CloseHandle(hSemaphore);</span><br><span class="line">	&#125;</span><br><span class="line">	CloseHandle(hFileMapping);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">Eating</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	Sleep(EATING_TIME);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><u>客户端进程</u></p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//framework.h</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// header.h: 标准系统包含文件的包含文件，</span></span><br><span class="line"><span class="comment">// 或特定于项目的包含文件</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">pragma</span> once</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"targetver.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> WIN32_LEAN_AND_MEAN             <span class="comment">// 从 Windows 头文件中排除极少使用的内容</span></span></span><br><span class="line"><span class="comment">// Windows 头文件</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;windows.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;CommCtrl.h&gt;</span></span></span><br><span class="line"><span class="comment">// C 运行时头文件</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;malloc.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;memory.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;tchar.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">pragma</span> comment ( lib , <span class="meta-string">"comctl32.lib"</span> )</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">pragma</span> comment(linker, \</span></span><br><span class="line">    <span class="string">"\"/manifestdependency:type='Win32' "</span>\</span><br><span class="line">    <span class="string">"name='Microsoft.Windows.Common-Controls' "</span>\</span><br><span class="line">    <span class="string">"version='6.0.0.0' "</span>\</span><br><span class="line">    <span class="string">"processorArchitecture='X86' "</span>\</span><br><span class="line">    <span class="string">"publicKeyToken='6595b64144ccf1df' "</span>\</span><br><span class="line">    <span class="string">"language='*'\""</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">//MainApp.cpp</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"framework.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"004PhilosophersDinner.h"</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAX_LOADSTRING 100</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> BUTTON_CLOSE 100</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> PHILOSOPHER_COUNT 5</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> WM_INVALIDATE WM_USER+1</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> _<span class="title">tagCOMMUNICATIONOBJECT</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    HWND hWnd;</span><br><span class="line">    BOOL bExitApplication;</span><br><span class="line">    <span class="keyword">int</span> iPhilosopherArray[PHILOSOPHER_COUNT];</span><br><span class="line">    <span class="keyword">int</span> iPhilosopherCounter;</span><br><span class="line">&#125;COMMUNICATIONOBJECT, * PCOMMUNICATIONOBJECT;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 全局变量:</span></span><br><span class="line">HINSTANCE hInst;                                <span class="comment">// 当前实例</span></span><br><span class="line">TCHAR szTitle[] = TEXT(<span class="string">"Philosophers Dinner Demo"</span>); <span class="comment">//标题名称</span></span><br><span class="line">TCHAR szWindowClass[] = TEXT(<span class="string">"__PD_WND_CLASS__"</span>);     <span class="comment">//窗口对象名称</span></span><br><span class="line">TCHAR szSemaphoreName[] = TEXT(<span class="string">"__PD_SEMAPHORE__"</span>);	<span class="comment">//信号量名称</span></span><br><span class="line">TCHAR szFileMappingName[] = TEXT(<span class="string">"__SHARED_FILE_MAPPING__"</span>);	<span class="comment">//进程共享虚拟映射文件名称</span></span><br><span class="line">PCOMMUNICATIONOBJECT pCommObject = <span class="literal">NULL</span>;            <span class="comment">//虚拟文件对象</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 此代码模块中包含的函数的前向声明:</span></span><br><span class="line"><span class="function">ATOM                <span class="title">MyRegisterClass</span><span class="params">(HINSTANCE hInstance)</span></span>;</span><br><span class="line"><span class="function">HWND                <span class="title">InitInstance</span><span class="params">(HINSTANCE, <span class="keyword">int</span>)</span></span>;</span><br><span class="line"><span class="function">LRESULT CALLBACK    <span class="title">WndProc</span><span class="params">(HWND, UINT, WPARAM, LPARAM)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">PhilosopherPass</span><span class="params">(<span class="keyword">int</span> iPhilosopher)</span></span>;          <span class="comment">//获取哲学家状态</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">FillEllipse</span><span class="params">(HWND hWnd,HDC hDC,<span class="keyword">int</span> iRight,<span class="keyword">int</span> iLeft,<span class="keyword">int</span> iTop,<span class="keyword">int</span> iBottom,<span class="keyword">int</span> iPass)</span></span>;    <span class="comment">//绘制圆</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> APIENTRY _tWinMain(_In_ HINSTANCE hInstance,</span><br><span class="line">                     _In_opt_ HINSTANCE hPrevInstance,</span><br><span class="line">                     _In_ LPWSTR    lpCmdLine,</span><br><span class="line">                     _In_ <span class="keyword">int</span>       nCmdShow)</span><br><span class="line">&#123;</span><br><span class="line">    UNREFERENCED_PARAMETER(hPrevInstance);</span><br><span class="line">    UNREFERENCED_PARAMETER(lpCmdLine);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// <span class="doctag">TODO:</span> 在此处放置代码。</span></span><br><span class="line">    HANDLE hFileMapping = CreateFileMapping((HANDLE)<span class="number">-1</span>, <span class="literal">NULL</span>, PAGE_READWRITE, <span class="number">0</span>, <span class="keyword">sizeof</span>(COMMUNICATIONOBJECT), szFileMappingName);</span><br><span class="line">    <span class="keyword">if</span> (!hFileMapping)</span><br><span class="line">    &#123;</span><br><span class="line">        MessageBox(<span class="literal">NULL</span>, TEXT(<span class="string">"Can not Create FileMapping!"</span>), TEXT(<span class="string">"Error!"</span>), MB_OK);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    pCommObject = (PCOMMUNICATIONOBJECT)MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">    <span class="keyword">if</span> (!pCommObject)</span><br><span class="line">    &#123;</span><br><span class="line">        MessageBox(<span class="literal">NULL</span>, TEXT(<span class="string">"Can not get access of File Mapping!"</span>), TEXT(<span class="string">"Error!"</span>), MB_OK);</span><br><span class="line">        CloseHandle(hFileMapping);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    InitCommonControls();                       <span class="comment">//初始化通用窗口组件</span></span><br><span class="line">    MyRegisterClass(hInstance);</span><br><span class="line"></span><br><span class="line">    HWND hWnd = InitInstance(hInstance, nCmdShow);</span><br><span class="line">    <span class="comment">// 执行应用程序初始化:</span></span><br><span class="line">    <span class="keyword">if</span> (!hWnd)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> FALSE;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//初始化虚拟文件指针</span></span><br><span class="line">    pCommObject-&gt;bExitApplication = FALSE;</span><br><span class="line">    pCommObject-&gt;hWnd = hWnd;</span><br><span class="line">    <span class="built_in">memset</span>(pCommObject-&gt;iPhilosopherArray, <span class="number">0</span>, <span class="keyword">sizeof</span>(*pCommObject-&gt;iPhilosopherArray));</span><br><span class="line">    pCommObject-&gt;iPhilosopherCounter = PHILOSOPHER_COUNT;</span><br><span class="line">    <span class="comment">//初始化信号量</span></span><br><span class="line">    HANDLE hSemaphore = CreateSemaphore(<span class="literal">NULL</span>, <span class="keyword">int</span>(PHILOSOPHER_COUNT / <span class="number">2</span>), <span class="keyword">int</span>(PHILOSOPHER_COUNT / <span class="number">2</span>), szSemaphoreName);</span><br><span class="line">    <span class="comment">//呼叫进程</span></span><br><span class="line">    STARTUPINFO startupInfo[PHILOSOPHER_COUNT] = &#123; &#123;<span class="number">0</span>&#125;,&#123;<span class="number">0</span>&#125;,&#123;<span class="number">0</span>&#125;,&#123;<span class="number">0</span>&#125;,&#123;<span class="number">0</span>&#125; &#125;;</span><br><span class="line">    PROCESS_INFORMATION processinformation[PHILOSOPHER_COUNT] = &#123; &#123;<span class="number">0</span>&#125;,&#123;<span class="number">0</span>&#125;,&#123;<span class="number">0</span>&#125;,&#123;<span class="number">0</span>&#125;,&#123;<span class="number">0</span>&#125; &#125;;</span><br><span class="line">    TCHAR szbuffer[<span class="number">8</span>];                            <span class="comment">//缓冲区</span></span><br><span class="line">    HANDLE hProcesses[PHILOSOPHER_COUNT];          <span class="comment">//进程句柄</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>;i&lt; PHILOSOPHER_COUNT;++i)</span><br><span class="line">    &#123;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> UNICODE</span></span><br><span class="line">        wsprintf(szbuffer, <span class="string">L"%d"</span>, i);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line">        <span class="built_in">sprintf</span>(szbuffer, <span class="string">"%d"</span>, i);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">        <span class="keyword">if</span> (CreateProcess(TEXT(<span class="string">"..\\Debug\\004Philosopher.exe"</span>), szbuffer,</span><br><span class="line">            <span class="literal">NULL</span>, <span class="literal">NULL</span>,</span><br><span class="line">            FALSE, <span class="number">0</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>, &amp;startupInfo[i], &amp;processinformation[i]))</span><br><span class="line">        &#123;</span><br><span class="line">            hProcesses[i] = processinformation[i].hProcess;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY004PHILOSOPHERSDINNER));</span><br><span class="line"></span><br><span class="line">    MSG msg;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 主消息循环:</span></span><br><span class="line">    <span class="keyword">while</span> (GetMessage(&amp;msg, <span class="literal">nullptr</span>, <span class="number">0</span>, <span class="number">0</span>))</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (!TranslateAccelerator(msg.hwnd, hAccelTable, &amp;msg))</span><br><span class="line">        &#123;</span><br><span class="line">            TranslateMessage(&amp;msg);</span><br><span class="line">            DispatchMessage(&amp;msg);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//释放数据</span></span><br><span class="line">    pCommObject-&gt;bExitApplication = TRUE;</span><br><span class="line">    UnmapViewOfFile(pCommObject);</span><br><span class="line">    <span class="comment">//等待所有进程执行完毕</span></span><br><span class="line">    WaitForMultipleObjects(PHILOSOPHER_COUNT, hProcesses, TRUE, INFINITE);  </span><br><span class="line">    <span class="comment">//释放句柄</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i=<span class="number">0</span>;i&lt; PHILOSOPHER_COUNT;++i)</span><br><span class="line">    &#123;</span><br><span class="line">        CloseHandle(hProcesses[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    CloseHandle(hSemaphore);</span><br><span class="line">    CloseHandle(hFileMapping);</span><br><span class="line">    <span class="keyword">return</span> (<span class="keyword">int</span>) msg.wParam;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//  函数: MyRegisterClass()</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//  目标: 注册窗口类。</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="function">ATOM <span class="title">MyRegisterClass</span><span class="params">(HINSTANCE hInstance)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    WNDCLASSEXW wcex;</span><br><span class="line"></span><br><span class="line">    wcex.cbSize = <span class="keyword">sizeof</span>(WNDCLASSEX);</span><br><span class="line"></span><br><span class="line">    wcex.style          = CS_HREDRAW | CS_VREDRAW;</span><br><span class="line">    wcex.lpfnWndProc    = WndProc;</span><br><span class="line">    wcex.cbClsExtra     = <span class="number">0</span>;</span><br><span class="line">    wcex.cbWndExtra     = <span class="number">0</span>;</span><br><span class="line">    wcex.hInstance      = hInstance;</span><br><span class="line">    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY004PHILOSOPHERSDINNER));</span><br><span class="line">    wcex.hCursor        = LoadCursor(<span class="literal">nullptr</span>, IDC_ARROW);</span><br><span class="line">    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+<span class="number">1</span>);</span><br><span class="line">    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_MY004PHILOSOPHERSDINNER);</span><br><span class="line">    wcex.lpszClassName  = szWindowClass;</span><br><span class="line">    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> RegisterClassExW(&amp;wcex);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//   函数: InitInstance(HINSTANCE, int)</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//   目标: 保存实例句柄并创建主窗口</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//   注释:</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//        在此函数中，我们在全局变量中保存实例句柄并</span></span><br><span class="line"><span class="comment">//        创建和显示主程序窗口。</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="function">HWND <span class="title">InitInstance</span><span class="params">(HINSTANCE hInstance, <span class="keyword">int</span> nCmdShow)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">   hInst = hInstance; <span class="comment">// 将实例句柄存储在全局变量中</span></span><br><span class="line"></span><br><span class="line">   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,</span><br><span class="line">      <span class="number">200</span>, <span class="number">200</span>, <span class="number">540</span>, <span class="number">590</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>, hInstance, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">   <span class="keyword">if</span> (!hWnd)</span><br><span class="line">   &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   HANDLE hFont = CreateFont(<span class="number">14</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, FW_NORMAL, FALSE, FALSE,</span><br><span class="line">       FALSE, BALTIC_CHARSET, OUT_DEFAULT_PRECIS,</span><br><span class="line">       CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_MODERN,</span><br><span class="line">       TEXT(<span class="string">"Microsoft Sans Serif"</span>));</span><br><span class="line"></span><br><span class="line">   HWND hButton = CreateWindow(TEXT(<span class="string">"BUTTON"</span>), TEXT(<span class="string">"Close"</span>),</span><br><span class="line">       WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,</span><br><span class="line">       <span class="number">410</span>, <span class="number">500</span>, <span class="number">100</span>, <span class="number">25</span>, hWnd, (HMENU)BUTTON_CLOSE, hInst, <span class="literal">NULL</span>);</span><br><span class="line">   SendMessage(hButton, WM_SETFONT, (WPARAM)hFont, TRUE);</span><br><span class="line">   ShowWindow(hWnd, nCmdShow);</span><br><span class="line">   UpdateWindow(hWnd);</span><br><span class="line"></span><br><span class="line">   <span class="keyword">return</span> hWnd;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//  目标: 处理主窗口的消息。</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//  WM_COMMAND  - 处理应用程序菜单</span></span><br><span class="line"><span class="comment">//  WM_PAINT    - 绘制主窗口</span></span><br><span class="line"><span class="comment">//  WM_DESTROY  - 发送退出消息并返回</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="function">LRESULT CALLBACK <span class="title">WndProc</span><span class="params">(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (message)</span><br><span class="line">    &#123;</span><br><span class="line">    <span class="keyword">case</span> WM_COMMAND:</span><br><span class="line">        &#123;</span><br><span class="line">        <span class="keyword">switch</span> (LOWORD(wParam))</span><br><span class="line">        &#123;</span><br><span class="line">        <span class="keyword">case</span> BUTTON_CLOSE:</span><br><span class="line">            DestroyWindow(hWnd);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> WM_INVALIDATE:</span><br><span class="line">        InvalidateRect(hWnd, <span class="literal">NULL</span>, TRUE);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> WM_PAINT:</span><br><span class="line">        &#123;</span><br><span class="line">            PAINTSTRUCT ps;</span><br><span class="line">            HDC hdc = BeginPaint(hWnd, &amp;ps);</span><br><span class="line">            <span class="comment">// <span class="doctag">TODO:</span> 在此处添加使用 hdc 的任何绘图代码...</span></span><br><span class="line">            FillEllipse(hWnd, hdc, <span class="number">210</span>, <span class="number">10</span>, <span class="number">310</span>, <span class="number">110</span>, PhilosopherPass(<span class="number">1</span>));</span><br><span class="line">            FillEllipse(hWnd, hdc, <span class="number">410</span>, <span class="number">170</span>, <span class="number">510</span>, <span class="number">270</span>, PhilosopherPass(<span class="number">2</span>));</span><br><span class="line">            FillEllipse(hWnd, hdc, <span class="number">335</span>, <span class="number">400</span>, <span class="number">435</span>, <span class="number">500</span>, PhilosopherPass(<span class="number">3</span>));</span><br><span class="line">            FillEllipse(hWnd, hdc, <span class="number">80</span>, <span class="number">400</span>, <span class="number">180</span>, <span class="number">500</span>, PhilosopherPass(<span class="number">4</span>));</span><br><span class="line">            FillEllipse(hWnd, hdc, <span class="number">10</span>, <span class="number">170</span>, <span class="number">110</span>, <span class="number">270</span>, PhilosopherPass(<span class="number">5</span>));</span><br><span class="line">            EndPaint(hWnd, &amp;ps);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> WM_DESTROY:</span><br><span class="line">        PostQuitMessage(<span class="number">0</span>);</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        <span class="keyword">return</span> DefWindowProc(hWnd, message, wParam, lParam);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">PhilosopherPass</span><span class="params">(<span class="keyword">int</span> iPhilosopher)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> pCommObject-&gt;iPhilosopherArray[iPhilosopher - <span class="number">1</span>];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">FillEllipse</span><span class="params">(HWND hWnd, HDC hDC, <span class="keyword">int</span> iLeft, <span class="keyword">int</span> iTop, <span class="keyword">int</span> iRight, <span class="keyword">int</span> iBottom, <span class="keyword">int</span> iPass)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    HBRUSH hBrush = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="keyword">if</span> (iPass)</span><br><span class="line">    &#123;</span><br><span class="line">        hBrush = CreateSolidBrush(RGB(<span class="number">255</span>,<span class="number">0</span>,<span class="number">0</span>));</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        hBrush = CreateSolidBrush(RGB(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>));</span><br><span class="line">    &#125;</span><br><span class="line">    HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hBrush);</span><br><span class="line">    Ellipse(hDC, iLeft, iTop, iRight, iBottom);</span><br><span class="line">    SelectObject(hDC, hOldBrush);</span><br><span class="line">    DeleteObject(hBrush);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="https://kriko.gitee.io/blog/2020/07/13/Day0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/blog/images/avatar.gif">
      <meta itemprop="name" content="kriko">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="GameDev">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/blog/2020/07/13/Day0/" class="post-title-link" itemprop="url">简单的开始</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-07-13 11:48:32" itemprop="dateCreated datePublished" datetime="2020-07-13T11:48:32+08:00">2020-07-13</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-11-05 10:06:11" itemprop="dateModified" datetime="2020-11-05T10:06:11+08:00">2020-11-05</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2/" itemprop="url" rel="index"><span itemprop="name">搭建博客</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="hexo-gitee"><a href="#hexo-gitee" class="headerlink" title="hexo+gitee"></a>hexo+gitee</h1><ol>
<li><p>建立完成之后上传至仓库</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">hexo clean <span class="comment">//清除缓存和public静态文件</span></span><br><span class="line">hexo g	   <span class="comment">//生成静态文件public</span></span><br><span class="line">hexo d		<span class="comment">//部署至指定仓库</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>如何新建一个文章</p>
<p><code>hexo new post &quot;article title</code> 指令可以在<code>post</code> 路径下创建一个新的<code>MakeDown</code>文件作为文章页面</p>
</li>
</ol>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">kriko</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/blog/archives/">
        
          <span class="site-state-item-count">3</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/blog/categories/">
          
        <span class="site-state-item-count">3</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/blog/tags/">
          
        <span class="site-state-item-count">6</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">kriko</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/blog/lib/anime.min.js"></script>
  <script src="/blog/lib/velocity/velocity.min.js"></script>
  <script src="/blog/lib/velocity/velocity.ui.min.js"></script>

<script src="/blog/js/utils.js"></script>

<script src="/blog/js/motion.js"></script>


<script src="/blog/js/schemes/pisces.js"></script>


<script src="/blog/js/next-boot.js"></script>




  















  

  

</body>
</html>
